/**
 * 文件子目录获取接口测试用例
 *
 * Created by snowingsea on 2020/02/26.
 */
const path = require('path');
const chai = require('chai');
const should = chai.should(); // eslint-disable-line no-unused-vars
chai.use(require('chai-http'));

const common = require('./../../common');
const Administrator = require('./../../../models/administrator');
const uri = require('./../uri');

const files = require('./../../../../phoenix/models/files');

module.exports = describe('/GET files/:id/children.json', function () {
  const administrator = new Administrator();
  let rootDirectory;
  const newUserIds = [];
  function url(fileId) {
    if (!fileId) {
      fileId = rootDirectory.fileId;
    }
    return `/files/${fileId}/children.json`;
  }

  before(function (done) {
    administrator.login()
      .then(() => administrator.createRandomTester())
      .then((tester) => {
        newUserIds.push(tester.userId);
        return tester.createRandomProject();
      })
      .then((project) => project.createRandomVersion())
      .then((res) => {
        rootDirectory = res.rootDirectory;
        done();
      })
      .catch(done);
  });
  after(function (done) {
    administrator.removeUsers(newUserIds)
      .then(() => {
        done();
      })
      .catch(done);
  });

  common.should.be.user(uri, url, 'get');
  common.should.be.tester(uri, url, 'get');

  // 正常请求
  const extNames = ['.a', '.ab', '.abc', '.x'];
  const data = [];
  for (let i = 0; i <= extNames.length; i += 1) {
    const item = [];
    for (let j = 0; j < i; j += 1) {
      item.push(extNames[j]);
    }
    data.push(item.length === 0 ? undefined : item);
  }
  data.forEach((extensions, index) => {
    const extensionsString = extensions ? ` with extensions=[${extensions}]` : '';
    it(`it should ${index === 0 ? 'GET' : 'get'} children${extensionsString}`, function (done) {
      let tree;
      rootDirectory.randomUpdate({ extNames })
        .then(() => rootDirectory.getTree())
        .then((res) => {
          tree = res;
          return rootDirectory.projectVersion.project.creator.login();
        })
        .then(() => {
          const root = tree.tree;
          const treeRootMap = new Map();
          const children = [root];
          while (children.length > 0) {
            const child = children.pop();
            treeRootMap.set(child.fileId, child);
            if (child.children) {
              child.children.forEach((grandson) => {
                children.push(grandson);
              });
            }
          }
          const promises = [];
          treeRootMap.forEach((root, fileId) => {
            // 按层检查
            promises.push(new Promise((resolve, reject) => { // eslint-disable-line no-unused-vars
              chai.request(uri)
                .get(url(fileId))
                .query({ extensions })
                .set('Authorization', `Bearer ${rootDirectory.projectVersion.project.creator.token.accessToken}`)
                .end((err, res) => {
                  res.should.have.status(200);
                  common.should.be.fileChildrenMessage(res.body);
                  if (root.kind === files.kind.file) { // 文件，无children
                    res.body.total.should.be.eql(0);
                    resolve();
                    return;
                  }

                  if (extensions) {
                    res.body.total.should.be.below(root.children.length + 1);
                  } else {
                    res.body.total.should.be.eql(root.children.length);
                  }
                  // 子目录数据应当包含在目录树数据中，且固定后缀
                  const treeChildren = root.children.map(({ fileId }) => fileId);
                  res.body.files.forEach(({ fileId, fileName, kind }) => {
                    treeChildren.should.be.contain(fileId);
                    if (kind === files.kind.file && extensions) {
                      extensions.should.be.contain(path.extname(fileName));
                    }
                  });
                  // 目录树的所有目录以及后缀范围内的文件应当都在子目录中
                  const children = res.body.files.map(({ fileId }) => fileId);
                  root.children.forEach(({ fileId, fileName, kind }) => {
                    if (kind === files.kind.directory
                      || !extensions
                      || extensions.indexOf(path.extname(fileName)) >= 0) {
                      children.should.be.contain(fileId);
                    }
                  });
                  resolve();
                });
            }));
          });
          return Promise.all(promises);
        })
        .then(() => {
          done();
        })
        .catch(done);
    });
  });

  // 不可获取不存在的文件子目录
  it('it should fail to get children when the file is not exists', function (done) {
    let newFileId;
    rootDirectory.createEmptyFile()
      .then(({ fileId }) => {
        newFileId = fileId;
        return rootDirectory.removeFile(fileId);
      })
      .then(() => rootDirectory.projectVersion.project.creator.login())
      .then(() => {
        chai.request(uri)
          .get(url(newFileId))
          .set('Authorization', `Bearer ${rootDirectory.projectVersion.project.creator.token.accessToken}`)
          .end((err, res) => {
            res.should.have.status(404);
            common.should.be.errorMessage(res.body);
            done();
          });
      })
      .catch(done);
  });

  // 不可获取他人的文件子目录
  it('it should fail to get children when the project is not yours', function (done) {
    let otherDirectoryId;
    administrator.createRandomTester()
      .then((newTester) => {
        newUserIds.push(newTester.userId);
        return newTester.createRandomProject();
      })
      .then((project) => project.createRandomVersion())
      .then(({ rootDirectory }) => {
        otherDirectoryId = rootDirectory.fileId;
        return rootDirectory.projectVersion.project.creator.login();
      })
      .then(() => {
        chai.request(uri)
          .get(url(otherDirectoryId))
          .set('Authorization', `Bearer ${rootDirectory.projectVersion.project.creator.token.accessToken}`)
          .end((err, res) => {
            res.should.have.status(404);
            common.should.be.errorMessage(res.body);
            done();
          });
      })
      .catch(done);
  });

  // 文件子目录下 files 为 0
  it('it should get 0 child for file ', function (done) {
    let newFileId;
    rootDirectory.createEmptyFile(files.kind.directory)
      .then((res) => res.createEmptyFile())
      .then(({ fileId }) => {
        newFileId = fileId;
        return rootDirectory.projectVersion.project.creator.login();
      })
      .then(() => {
        chai.request(uri)
          .get(url(newFileId))
          .set('Authorization', `Bearer ${rootDirectory.projectVersion.project.creator.token.accessToken}`)
          .end((err, res) => {
            res.should.have.status(200);
            common.should.be.fileChildrenMessage(res.body);
            res.body.total.should.be.eql(0);
            done();
          });
      })
      .catch(done);
  });
});
